package org.filecollector.filecontroller.virtualcatalogue.virtualfile;

import junit.framework.TestCase;
import org.junit.Test;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.file.Files;
import java.util.*;

public class TestVirtualFileSM {

    @Test
    public void TestDebugMessage() {
        String filepath = "\\home";
        String ifTrue = "true";
        String ifFalse = "false";
        ArrayList<String> ret = new ArrayList<>();
        VirtualFileStaticMethods.debugMessage(
                filepath,
                ret::add,
                true,
                ifTrue,
                "FAIL"
        );//Required message with ifTrue
        VirtualFileStaticMethods.debugMessage(
                filepath,
                ret::add,
                false,
                "FAIL",
                ifFalse
        );//Required message with ifFalse
        VirtualFileStaticMethods.debugMessage(
                "FAIL",
                ret::add,
                true,
                "FAIL",
                "FAIL"
        );//Required nothing
        ArrayList<String> expect = new ArrayList<>(
                List.of(
                        String.format("File %s %s", filepath, ifTrue),
                        String.format("File %s %s", filepath, ifFalse)
                )
        );
        TestCase.assertEquals(expect, ret);
    }

    @Test
    public void TestExisting() {
        File check = new File("test");
        File nullFile = new File("test_none");
        if (check.exists()) {
            check.delete();
        }
        TestCase.assertFalse(VirtualFileStaticMethods.exists(check, (String _) -> {}));
        try {
            check.createNewFile();
            check.deleteOnExit();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        TestCase.assertTrue(VirtualFileStaticMethods.exists(check, (String _) -> {}));
    }

    @Test
    public void TestCheckSum() {
        File check = new File("test");
        try {
            if (!check.createNewFile()) {
                throw new RuntimeException("Something went wrong");
            }
            check.deleteOnExit();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        TestCase.assertEquals(
                (Long) 1488L,
                VirtualFileStaticMethods.getCheckSum(
                        (InputStream _) -> OptionalLong.of(1488L),
                        check,
                        (String _) -> {}
                )
        );
    }

    @Test
    public void TestWriteDirectly() {
        File check = new File("Test");
        try {
            if (!check.createNewFile()) {
                throw new RuntimeException("Something went wrong");
            }
            check.deleteOnExit();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        String initText = "START";
        String addText = "ADD";
        VirtualFileStaticMethods.writeDirectly(
                initText.toCharArray(),
                check,
                false,
                (String _) -> {},
                (String _) -> {}
        );
        try(InputStream is = Files.newInputStream(check.toPath())) {
            TestCase.assertEquals(new String(is.readAllBytes()), initText);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        VirtualFileStaticMethods.writeDirectly(
                addText.toCharArray(),
                check,
                true,
                (String _) -> {},
                (String _) -> {}
        );
        try(InputStream is = Files.newInputStream(check.toPath())) {
            TestCase.assertEquals(new String(is.readAllBytes()), initText+addText);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    @Test
    public void TestTouch() {
        File file = new File("test");
        file.deleteOnExit();
        TestCase.assertTrue(
                VirtualFileStaticMethods.touch(
                    file.getAbsolutePath(),
                    (String _) -> {},
                    (String _) -> {}
                )
        );
        TestCase.assertTrue(file.exists());
    }

    @Test
    public void TestReadDirectly() {
        String data = "01249781891y1390t2930";
        File file = new File("test");
        try(OutputStream os = Files.newOutputStream(file.toPath())){
            os.write(data.getBytes());
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        var ret = VirtualFileStaticMethods.readDirectly(5, file, (String _) -> {}, (String _) -> {});
        var check = Arrays.copyOf(data.toCharArray(), 5);
        for (int i = 0; i<5; i++){
            TestCase.assertEquals(ret[i], check[i]);
        }
        ret = VirtualFileStaticMethods.readDirectly(data.length(), file, (String _) -> {}, (String _) -> {});
        check = data.toCharArray();
        for (int i = 0; i < 5; i++) {
            TestCase.assertEquals(ret[i], check[i]);
        }
    }


}
